#include "system/logger.h"
#include "system/loggerlistener.h"

#include <stdarg.h>
#include <stdio.h>

namespace dw {
	namespace system {

//------------------------------------------------------------------------------
// Helpers
//------------------------------------------------------------------------------

//------------------------------------------------------------------------------
const std::string& Logger::levelToString(Level level)
{
	dwAssert(level < LVL_COUNT, "Invalid parameter: level is out of bounds");

	return _levelNames[(int)level];
}

//------------------------------------------------------------------------------
// Command
//------------------------------------------------------------------------------

//------------------------------------------------------------------------------
void Logger::log(Logger::Level level, const char* format, ...)
{
	dwAssert(level < LVL_COUNT, "Invalid parameter: level is out of bounds");
	dwAssert(format != NULL, "Invalid parameter: format == NULL");

	if (!levelIsEnabled(level))
		return ;

	static char buffer[256];
	va_list params;

	va_start(params, format);
	vsprintf_s(buffer, format, params);
	va_end(params);

	_logInternal(level, buffer);
}

//------------------------------------------------------------------------------
void Logger::debug(const char* format, ...)
{
	dwAssert(format != NULL, "Invalid parameter: format == NULL");

	if (!levelIsEnabled(LVL_DEBUG))
		return ;

	static char buffer[256];
	va_list params;

	va_start(params, format);
	vsprintf_s(buffer, format, params);
	va_end(params);

	_logInternal(LVL_DEBUG, buffer);
}

//------------------------------------------------------------------------------
void Logger::inform(const char* format, ...)
{
	dwAssert(format != NULL, "Invalid parameter: format == NULL");

	if (!levelIsEnabled(LVL_INFO))
		return ;

	static char buffer[256];
	va_list params;

	va_start(params, format);
	vsprintf_s(buffer, format, params);
	va_end(params);

	_logInternal(LVL_INFO, buffer);
}

//------------------------------------------------------------------------------
void Logger::warn(const char* format, ...)
{
	dwAssert(format != NULL, "Invalid parameter: format == NULL");

	if (!levelIsEnabled(LVL_WARNING))
		return ;

	static char buffer[1024];
	va_list params;

	va_start(params, format);
	vsprintf_s(buffer, format, params);
	va_end(params);

	_logInternal(LVL_WARNING, buffer);
}

//------------------------------------------------------------------------------
void Logger::error(const char* format, ...)
{
	dwAssert(format != NULL, "Invalid parameter: format == NULL");

	if (!levelIsEnabled(LVL_ERROR))
		return ;

	static char buffer[256];
	va_list params;

	va_start(params, format);
	vsprintf_s(buffer, format, params);
	va_end(params);

	_logInternal(LVL_ERROR, buffer);
}

//------------------------------------------------------------------------------
void Logger::registerListener(Listener* listener)
{
	dwAssert(listener != NULL, "Invalid parameter: listener == NULL");

	_listeners.push_back(listener);
	listener->start();
}

//------------------------------------------------------------------------------
void Logger::unregisterListener(Listener* listener)
{
	dwAssert(listener != NULL, "Invalid parameter: listener == NULL");

	ListenerCollection::iterator foundIt = std::find(_listeners.begin(), _listeners.end(), listener);

	dwAssert(foundIt != _listeners.end() && *foundIt == listener, "Can't find this listener");
	(*foundIt)->stop();
	_listeners.erase(foundIt);
}

//------------------------------------------------------------------------------
// Helpers
//------------------------------------------------------------------------------

//------------------------------------------------------------------------------
void Logger::_logInternal(Level level, const std::string& message)
{
	ListenerCollection::iterator it;

	for (it = _listeners.begin(); it != _listeners.end(); ++it)
	{
		dwAssert((*it) != NULL, "ListenerCollection is corrupted");

		(*it)->log(level, message);
	}
}

//------------------------------------------------------------------------------
// Data
//------------------------------------------------------------------------------

/*static*/ const std::string Logger::_levelNames[Logger::LVL_COUNT] = {
	"Debug",
	"Information",
	"Warning",
	"Error"
};


	} // namespace system
} // namespace dw
